package edu.pitt.dbmi.odie.gapp.gwt.server.user;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.security.GeneralSecurityException;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import com.allen_sauer.gwt.log.client.Log;
import com.google.appengine.api.users.User;
import com.google.gdata.client.http.AuthSubUtil;
import com.google.gdata.util.AuthenticationException;

import edu.pitt.dbmi.odie.gapp.gwt.server.util.rest.ODIE_NcboRestUtils;

@SuppressWarnings("serial")
public class ODIE_ServerSideLoginInfo extends DefaultHandler implements Serializable {

	/**
	 * Field logger.
	 */
	private static final Logger logger = Logger
			.getLogger(ODIE_ServerSideLoginInfo.class);

	private boolean isReadingDocuments ;
	
	private String hostedDomain; // e.g, webodie.net
	private String authDomain;
	private String emailAddress;
	private String nickName;
	private String authSubToken;
	private String authSubSessionToken;
	private String authzGDataToken;
	private String password;
	private String documentEntryText;
	private String xmlizedClientParams;
	private String xmlizedInitParams;

	private StringBuffer accumulator; // Accumulate text

	private ArrayList<ODIE_Param> params = new ArrayList<ODIE_Param>();
	private ODIE_Param paramObj;

	public ODIE_ServerSideLoginInfo() {
	}

	public void cacheParameters() {
		try {
			
			if (ODIE_NcboRestUtils.isPosLen(xmlizedClientParams)) {
				readXmlStream(new ByteArrayInputStream(xmlizedClientParams
						.getBytes()));
			}
			if (ODIE_NcboRestUtils.isPosLen(xmlizedInitParams)) {
				readXmlStream(new ByteArrayInputStream(xmlizedInitParams
						.getBytes()));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}

	private void readXmlStream(InputStream is) throws IOException, SAXException {
		XMLReader parser = new SAXParser();
		parser.setFeature("http://xml.org/sax/features/validation", false);
		parser.setContentHandler(this);
		parser.setErrorHandler(this);
		InputSource input = new InputSource(is);
		input.setEncoding("ISO-8859-1");
		parser.parse(input);
		is.close();
	}
	
	public String toString() {
		StringBuffer sb = new StringBuffer() ;
		sb.append("emailAddress => " + emailAddress + "\n") ;
		sb.append("nickName => " + nickName + "\n") ;
		sb.append("authSubToken => " + authSubToken + "\n") ;
		sb.append("authSubSessionToken => " + authSubSessionToken + "\n") ;
		sb.append("authzGDataToken => " + authzGDataToken + "\n") ;
		return sb.toString() ;
	}

	public void startDocument() {
		accumulator = new StringBuffer();
	}

	public void characters(char[] buffer, int start, int length) {
		accumulator.append(buffer, start, length);
	}

	public void startElement(String namespaceURL, String localName,
			String qname, Attributes attributes) {
		if (localName.equals("param")) {
			this.paramObj = new ODIE_Param();
		}
		accumulator.setLength(0);
	}

	public void endElement(String namespaceURL, String localName, String qname) {
		try {
			if (localName.equals("param")) {
				this.params.add(this.paramObj);
				this.paramObj = null;
			} else if (localName.equals("key")) {
				this.paramObj.key = accumulator.toString().trim();
			} else if (localName.equals("value")) {
				this.paramObj.value = accumulator.toString().trim();
			}
		} catch (Exception x) {
			x.printStackTrace();
		}
	}

	// Called at the end of parsing. Used here to print our results.
	public void endDocument() {
		for (ODIE_Param param : params) {
			if (param.key.equals("password")) {
				this.password = param.value;
				Log.debug("Parsed password ==> " + this.password) ;
			} else if (param.key.equals("token")) {
				this.authSubToken = param.value;
				Log.debug("Parsed authSubToken ==> " + this.authSubToken) ;
				exchangeForAuthSubSessionToken();
			} else if (param.key.equals("sessionToken")) {
				this.authSubSessionToken = param.value ;
				Log.debug("Parsed authSubSessionToken ==> " + this.authSubSessionToken) ;
			}
		}
	}

	private void exchangeForAuthSubSessionToken() {
		try {
//			this.authSubSessionToken = AuthSubUtil.exchangeForSessionToken(
//					"http", "webodie.net", this.authSubToken, null);
			Log.debug(this.authSubSessionToken) ;
			this.authSubSessionToken = AuthSubUtil.exchangeForSessionToken(
					this.authSubToken, null);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (GeneralSecurityException e) {
			e.printStackTrace();
		}
	}

	// Issue a warning
	public void warning(SAXParseException exception) {
		logger.warn("WARNING: line " + exception.getLineNumber() + ": "
				+ exception.getMessage());
	}

	// Report a parsing error
	public void error(SAXParseException exception) {
		logger.warn("ERROR: line " + exception.getLineNumber() + ": "
				+ exception.getMessage());
	}

	// Report a non-recoverable error and exit
	public void fatalError(SAXParseException exception) throws SAXException {
		logger.fatal("FATAL: line " + exception.getLineNumber() + ": "
				+ exception.getMessage());
		throw (exception);
	}
	
	private User user;
	
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
		if (user != null) {
			setAuthDomain(user.getAuthDomain()) ;
			setEmailAddress(user.getEmail()) ;
			setNickName(user.getNickname()) ;
		}
	}
	
	public String getHostedDomain() {
		return hostedDomain;
	}

	public void setHostedDomain(String hostedDomain) {
		this.hostedDomain = hostedDomain;
	}

	public boolean isReadingDocuments() {
		return isReadingDocuments;
	}

	public void setReadingDocuments(boolean isReadingDocuments) {
		this.isReadingDocuments = isReadingDocuments;
	}

	public String getDocumentEntryText() {
		return (documentEntryText == null) ? "UNDEFINED" : documentEntryText;
	}

	public void setDocumentEntryText(String documentEntryText) {
		this.documentEntryText = documentEntryText;
	}
	
	public String getAuthDomain() {
		return (authDomain == null) ? "UNDEFINED" : authDomain;
	}

	public void setAuthDomain(String authDomain) {
		this.authDomain = authDomain;
	}

	public String getEmailAddress() {
		return (emailAddress == null) ? "UNDEFINED" : emailAddress;
	}

	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}
	
	public String getNickName() {
		return (nickName == null) ? "UNDEFINED" : nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	public String getAuthSubToken() {
		return (authSubToken == null) ? "UNDEFINED" : authSubToken;
	}

	public void setAuthSubToken(String authSubToken) {
		this.authSubToken = authSubToken;
	}

	public String getAuthSubSessionToken() {
		return (authSubSessionToken == null) ? "UNDEFINED" : authSubSessionToken;
	}

	public void setAuthSubSessionToken(String authSubSessionToken) {
		this.authSubSessionToken = authSubSessionToken;
	}
	
	public String getAuthzGDataToken() {
		return authzGDataToken;
	}

	public void setAuthzGDataToken(String authzGDataToken) {
		this.authzGDataToken = authzGDataToken;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getXmlizedClientParams() {
		return xmlizedClientParams;
	}

	public void setXmlizedClientParams(String xmlizedClientParams) {
		this.xmlizedClientParams = xmlizedClientParams;
	}

	public String getXmlizedInitParams() {
		return xmlizedInitParams;
	}

	public void setXmlizedInitParams(String xmlizedInitParams) {
		this.xmlizedInitParams = xmlizedInitParams;
	}

}
